﻿#pragma execution_character_set("utf-8")

#include "SerialPort.hpp"

#include <QByteArray>
#include <QDate>
#include <QDateTime>
#include <QSerialPortInfo>
#include <QTime>

// namespace qmlserialport {
using namespace std;
SerialPort::SerialPort(QObject *parent)
    : QObject(parent), baudRate_(115200), dataBits_(8),
      flowControl_(NoFlowControl), parity_(NoParity), stopBits_(OneStop),
      m_speed(0) {
  connect(&serialPort, SIGNAL(readyRead()), this, SLOT(readyRead()));
  connect(&serialPort, &QSerialPort::errorOccurred, this,
          &SerialPort::onConnectionError);

  updater = new Updater();
  connect(updater, SIGNAL(sendData(QByteArray)), this,
          SLOT(sendData(QByteArray)));
  connect(this, SIGNAL(dataReceived(QByteArray)), updater,
          SLOT(unpackData(QByteArray)));

  //转发signal
  connect(updater, SIGNAL(progressChanged(float)), this,
          SIGNAL(progressChanged(float)));
  connect(updater, SIGNAL(downloadComplete()), this,
          SIGNAL(downloadComplete()));

  connect(updater, SIGNAL(downloadProgress(int, int)), this,
          SIGNAL(downloadProgress(int, int)));

  connect(updater, SIGNAL(downReplyTimeout()), this,
          SIGNAL(downReplyTimeout()));
  connect(updater, SIGNAL(packReplyTimeout()), this,
          SIGNAL(packReplyTimeout()));
  connect(updater, SIGNAL(addDownLog(QString)), this,
          SIGNAL(addDownLog(QString)));
  connect(updater, SIGNAL(downloadRunning()), this, SIGNAL(downloadRunning()));
}

SerialPort::~SerialPort() { this->close(); }

void SerialPort::setDeviceName(QString deviceName) {
  deviceName_ = deviceName;
  emit deviceNameChanged();
}

QString SerialPort::praseImei(QString topic) {
  QString imei = topic.mid(9, topic.length() - 13);
  //  regex pattern("/sys/p2p/11/pub");
  return imei;
}

void SerialPort::setPortName(QString portName) {
  portName_ = portName;
  emit portNameChanged();
}

void SerialPort::setBaudRate(int baudRate) {
  if (baudRate <= 0) {
    qDebug() << "Baud rate must be positive, setting to 115200";
    baudRate_ = 115200;
  } else
    baudRate_ = baudRate;
  emit baudRateChanged();
}

void SerialPort::setDataBits(int dataBits) {
  if (dataBits < 5 || 8 < dataBits) {
    qDebug() << "Data bits must be between 5 and 8, setting to 8";
    dataBits_ = 8;
  } else
    dataBits_ = dataBits;
  emit dataBitsChanged();
}

void SerialPort::setFlowControl(FlowControl flowControl) {
  flowControl_ = flowControl;
  emit flowControlChanged();
}

void SerialPort::setParity(Parity parity) {
  parity_ = parity;
  emit parityChanged();
}

void SerialPort::setStopBits(StopBits stopBits) {
  stopBits_ = stopBits;
  emit stopBitsChanged();
}

bool SerialPort::open() {
  serialPort.close();
  serialPort.setPortName(portName_);
  serialPort.setBaudRate(baudRate_);
  serialPort.setDataBits(static_cast<QSerialPort::DataBits>(dataBits_));
  serialPort.setFlowControl(
      static_cast<QSerialPort::FlowControl>(flowControl_));
  serialPort.setParity(static_cast<QSerialPort::Parity>(parity_));
  serialPort.setStopBits(static_cast<QSerialPort::StopBits>(stopBits_));
  bool ret = serialPort.open(QIODevice::ReadWrite);
  qDebug() << "open serial port " << portName_ << " status:" << ret;
  QTimer::singleShot(1000, this, SLOT(speedCntTimeout()));
  return ret;
}

void SerialPort::close() {
  qDebug() << "close serial port " << portName_;
  serialPort.close();
}

void SerialPort::sendData(QByteArray data) {
  qDebug() << "serial send size:" << data.size();
  serialPort.write(data);
  m_speed += data.size();
}

void SerialPort::readyRead() {
  QByteArray data = serialPort.readAll();
  qDebug() << "serial read size:" << data.size();
  emit dataReceived(data);
}

QStringList SerialPort::getPortsInfo() {

  QStringList list;
  const auto infos = QSerialPortInfo::availablePorts();
  for (const QSerialPortInfo &info : infos) {
    //    QString inf = info.portName() + tr(",") + info.description();
    list << info.portName();
    //    qDebug() << info.portName() << " " << info.description();
  }
  return list;
}

bool SerialPort::getStatus() { return serialPort.isOpen(); }

QString SerialPort::stringToHex(QByteArray msg) {
  int i;
  QString ret;
  uint8_t len = msg.size(); //获取字符串中的字符个数
  for (i = 0; i < len; i++) //循环判断当前字符是数字还是小写字符还是大写字母
  {
    uchar pp = msg.at(i) & 0xff;
    ret.append(QString().sprintf("%02X ", pp));
  }
  return ret;
}

void SerialPort::onConnectionError(QSerialPort::SerialPortError error) {
  if (error == WriteError || error == ReadError || error == ResourceError) {
    serialPort.close();
    emit connectFailed(deviceName_);
  }
}

QString SerialPort::getTs() {
  QString time;
  time = QDateTime::currentDateTime().toString(
      QStringLiteral("yyyy-MM-dd HH:mm:ss:zzz"));
  return time;
}

QString SerialPort::error() {
  QSerialPort::SerialPortError e = serialPort.error();
  switch (e) {
  case DeviceNotFoundError:
    return tr("设备不存在！");
  case PermissionError:
    return tr("权限不足！");
  default:
    return tr("打开失败！");
  }
}

void SerialPort::speedCntTimeout() {
  QTimer::singleShot(1000, this, SLOT(speedCntTimeout()));
  emit speedUpdate(m_speed);
  m_speed = 0;
}

void SerialPort::startUpdate(QByteArray fw) {
  updater->setFirmware(fw);
  updater->startDownload();
}

//} // namespace qmlserialport
